#include <mysql/mysql.h>
#include <iostream>
#include <vector>
#include <chrono>

using namespace std;

const char* gHost = "localhost";
const char* gUsername = "root";
const char* gPassword = "admin";
const char* gDatabase = "aoo";

//class TestDyncObject {


// 写入 objectNum 个对象； 每个对象有 attrNum个属性
int testWriteObjct(const std::string& objectName, const int objectNum, const int attrNum) {
    MYSQL* conn;
    MYSQL_RES* res;
    MYSQL_ROW row;

    conn = mysql_init(nullptr);

    // 建立MySQL连接
    if (!mysql_real_connect(conn, gHost, gUsername, gPassword, gDatabase, 0, nullptr, 0)) {
        cout << "连接数据库失败：" << mysql_error(conn) << endl;
        return 1;
    }

  
    auto start = std::chrono::high_resolution_clock::now();

    std::vector<std::string> attrIds(attrNum);
    
    // 插入属性元数据
    for(int i=0; i<attrNum; ++i ) {
        std::string no = std::to_string(i + 1);
        std::string id = objectName + "_" + no;
        std::string insertAttributeMetadata = "INSERT INTO dataplatform_attribute (id, attribute_key, attribute_name_cn, attribute_code, attribute_data_type) VALUES ('" + id + "','attribute_key_" + no +"','attribute_name_" + no +"','attribute_code_" + no + "','dt')";
        if (mysql_query(conn, insertAttributeMetadata.c_str())) {
            std::cout << "Failed to insert attribute metadata: " << mysql_error(conn) << std::endl;
            return 1;
        }

        // 获取插入的属性元数据的ID
        //attrIds[i] = mysql_insert_id(conn);
        attrIds[i] = id;
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    std::cout << "Meta attribute insert, execution time: " << duration << " milliseconds" << std::endl;

    start = std::chrono::high_resolution_clock::now();

    // 插入对象类实例
    for (int i=0; i<objectNum; ++i ) {
        std::string classInstanceId = objectName + "_" + ::to_string(i + 1);

        std::string insertClassInstance = "INSERT INTO dataplatform_class_instance (id, instance_code, class_id) VALUES ('" + classInstanceId + "','" + objectName + std::to_string(i) + "','meta_class_id')";
        if (mysql_query(conn, insertClassInstance.c_str())) {
            std::cout << "Failed to insert class instance: " << mysql_error(conn) << std::endl;
            return 1;
        }

        // 获取插入的对象类实例的ID
        //unsigned int classInstanceId = mysql_insert_id(conn);
        

        // 插入属性实例数据
        for (int attr = 0; attr < attrNum; ++attr) {
         //   std::cout << "will insert attribute instance: " << i*attrNum+attr+1 << std::endl;
                
            std::string insertAttributeInstance = "INSERT INTO dataplatform_attr_instance (id, instance_code, attr_id, value, class_instance_id) VALUES ('" + objectName + "_" + std::to_string(i*attrNum+attr+1) + "','" + objectName + std::to_string(i) + "','"  + attrIds[attr] + "', 'attr_value_" + classInstanceId + "_" + std::to_string(attr) + "', '" + classInstanceId + "')";

            if (mysql_query(conn, insertAttributeInstance.c_str())) {
                std::cout << "Failed to insert attribute instance: " << mysql_error(conn) << std::endl;
                return 1;
            }
        }

        static int64_t last_dt = 0;
        auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
        if (dt - last_dt > 2000) {
            std::cout << "Current insert " << i << " Objects with " << attrNum << " for each object, execution time: " << dt << " milliseconds" << std::endl;
            last_dt = dt;
        }
    }

    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    std::cout << "Total for insert " << objectNum << " Objects with " << attrNum << " attributes for each object, execution time: " << duration << " milliseconds" << std::endl;

    // 关闭MySQL连接
    mysql_close(conn);
    
    return 0;
}



int testRead(const std::string& objectName, const int objectNum, const int attrNum) {
    // 连接数据库
    MYSQL *conn;
    conn = mysql_init(NULL);
    if (!mysql_real_connect(conn, gHost, gUsername, gPassword, gDatabase, 0, nullptr, 0)) {
        std::cout << "Failed to connect to database: " << mysql_error(conn) << std::endl;
        return 1;
    }

    auto start = std::chrono::high_resolution_clock::now();

    // 根据对象实例的代码查找对象
    for (int i=0; i<objectNum; ++i) {
        std::string selectClassInstance = "SELECT * FROM dataplatform_class_instance WHERE instance_code = '" + objectName + std::to_string(i) + "'";
        if (mysql_query(conn, selectClassInstance.c_str())) {
            std::cout << "Failed to select class instance: " << mysql_error(conn) << std::endl;
            return 1;
        }

        // 获取查询结果
        MYSQL_RES *result = mysql_store_result(conn);
        if (result == NULL) {
            std::cout << "Failed to get result: " << mysql_error(conn) << std::endl;
            return 1;
        }

        // 获取对象的ID
        MYSQL_ROW row = mysql_fetch_row(result);
        std::string classInstanceId = row[0];

        // 根据对象的ID查找属性实例
        std::string selectAttributeInstance = "SELECT * FROM dataplatform_attr_instance WHERE class_instance_id = '" + classInstanceId + "'";
        if (mysql_query(conn, selectAttributeInstance.c_str())) {
            std::cout << "Failed to select attribute instance: " << mysql_error(conn) << std::endl;
            return 1;
        }

        // 获取查询结果
        MYSQL_RES *attributeResult = mysql_store_result(conn);
        if (attributeResult == NULL) {
            std::cout << "Failed to get attribute result: " << mysql_error(conn) << std::endl;
            return 1;
        }


        static int64_t last_dt = 0;
        auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
        if (dt - last_dt > 2000) {
            std::cout << "Current read " << i << " Objects with " << attrNum << " for each object, execution time: " << dt << " milliseconds" << std::endl;
        
            // 遍历查询结果并打印属性值
            MYSQL_ROW attributeRow;
            while ((attributeRow = mysql_fetch_row(attributeResult))) {
                std::cout << "attribute_id: " << attributeRow[0] << std::endl;
                std::cout << "attribute_key: " << attributeRow[1] << std::endl;
                std::cout << "attribute_value: " << attributeRow[2] << std::endl;
                std::cout << "class_instance_id: " << attributeRow[3] << std::endl;
                std::cout << std::endl;
            }

            last_dt = dt;
        }


        // 释放查询结果内存
        mysql_free_result(attributeResult);
        mysql_free_result(result);       
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    std::cout << "Total for read " << objectNum << " Objects with " << attrNum << " attributes for each object, execution time: " << duration << " milliseconds" << std::endl;


    // 关闭数据库连接
    mysql_close(conn);

    return 0;
}


int main(int argc, char* argv[]) {
    if (argc < 8) {
        std::cout << "Please provide 7 arguments: host, username, passwrod, database; object name, object num, attribute num for each object." << std::endl;
        return 1;
    }
    
    // Access the command line arguments
    gHost = argv[1];
    gUsername = argv[2];
    gPassword = argv[3];
    gDatabase = argv[4];

    std::string objName = argv[5];
    int objectNum = std::atoi(argv[6]);
    int attrNum = std::atoi(argv[7]);
    
    testWriteObjct(objName, objectNum, attrNum);
    testRead(objName, objectNum, attrNum);

    return 0;
}
